import React, { useEffect, useRef, useState, useCallback } from 'react'
//加密
import CryptoJS from 'crypto-js'
import { JSEncrypt } from 'jsencrypt'
import { current } from '@reduxjs/toolkit'

//对称加密aes
export const aesUtil = {
  // 获取key
  genKey: function (length = 16) {
    let random = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
    let str = ''
    for (let i = 0; i < length; i++) {
      str = str + random.charAt(Math.random() * random.length)
    }
    return str
  },

  // 加密
  encrypt: function (plaintext, key) {
    if (plaintext instanceof Object) {
      // JSON.stringify
      plaintext = JSON.stringify(plaintext)
    }
    // 这里前后端一定要对应
    let encrypted = CryptoJS.AES.encrypt(
      CryptoJS.enc.Utf8.parse(plaintext),
      CryptoJS.enc.Utf8.parse(key),
      {
        iv: CryptoJS.enc.Utf8.parse('af25-87hk-a35v-5'),
        mode: CryptoJS.mode.CBC,
        padding: CryptoJS.pad.Pkcs7
      }
    )
    return encrypted.toString()
  },

  // 解密
  decrypt: function (ciphertext, key) {
    let decrypt = CryptoJS.AES.decrypt(ciphertext, CryptoJS.enc.Utf8.parse(key), {
      iv: CryptoJS.enc.Utf8.parse('af25-87hk-a35v-5'),
      mode: CryptoJS.mode.CBC,
      padding: CryptoJS.pad.Pkcs7
    })
    let decString = CryptoJS.enc.Utf8.stringify(decrypt)
    if (decString[0] === '{' || decString.charAt[0] === '[') {
      // JSON.parse
      decString = JSON.parse(decString)
    }
    return decString
  }
}

//非对称加密rsa
export const rsaUtil = {
  // RSA 位数，要跟后端对应
  bits: 1024,

  // 当前JSEncrypted对象
  thisKeyPair: {},

  // 生成密钥对(公钥和私钥)
  genKeyPair: function (bits = rsaUtil.bits) {
    let genKeyPair = {}
    rsaUtil.thisKeyPair = new JSEncrypt({
      default_key_size: bits
    })

    // 获取私钥
    genKeyPair.privateKey = rsaUtil.thisKeyPair.getPrivateKey()

    // 获取公钥
    genKeyPair.publicKey = rsaUtil.thisKeyPair.getPublicKey()

    return genKeyPair
  },

  // 公钥加密
  encrypt: function (plaintext, publicKey) {
    // 生成密钥对(公钥和私钥)
    this.genKeyPair()

    if (plaintext instanceof Object) {
      plaintext = JSON.stringify(plaintext)
    }
    publicKey && rsaUtil.thisKeyPair.setPublicKey(publicKey)
    return rsaUtil.thisKeyPair.encrypt(JSON.stringify(plaintext))
  },

  // 私钥解密
  decrypt: function (ciphertext, privateKey) {
    privateKey && rsaUtil.thisKeyPair.setPrivateKey(privateKey)
    let decString = rsaUtil.thisKeyPair.decrypt(ciphertext)
    decString = decodeURIComponent(encodeURIComponent(decString).replaceAll('%22', ''))
    if (decString.charAt(0) === '{' || decString.charAt(0) === '[') {
      // JSON.parse
      decString = JSON.parse(decString)
    }
    return decString
  }
}

// 加工时间戳
export const handlerDate = time => {
  const date = new Date(+time)
  const year = date.getFullYear()
  const moths = (date.getMonth() + 1).toString().padStart(2, '0')
  const day = date.getDate().toString().padStart(2, '0')

  return `${year}-${moths}-${day}`
}

//封装localStorage
export const storage = {
  storageName: 'jira',
  getStorage: () => {
    return JSON.parse(window.localStorage.getItem(storage.storageName) || '{}')
  },
  getItem: key => {
    let data = storage.getStorage()

    return data[key] !== undefined ? data[key] : null
  },
  setItem: (key, value) => {
    let data = storage.getStorage()
    data[key] = value
    window.localStorage.setItem(storage.storageName, JSON.stringify(data))
  },
  //一次性添加多项，{key1: value1,key2:value2},参数为对象
  setItemList: obj => {
    let data = storage.getStorage()

    for (let key in obj) {
      data[key] = obj[key]
    }

    window.localStorage.setItem(storage.storageName, JSON.stringify(data))
  },
  removeItem: key => {
    let data = storage.getStorage()
    delete data[key]
    window.localStorage.setItem(storage.storageName, JSON.stringify(data))
  },
  clear: () => {
    window.localStorage.removeItem(storage.storageName)
  }
}

/**
 * 分堆渲染
 * @param {任务长度} maxCount
 */
export const useDefer = maxCount => {
  const [time, setTime] = useState(1)

  //一次完成的任务数量
  const workTime = 1

  requestAnimationFrame(() => {
    if (time >= maxCount) {
      return
    }
    setTime(time => time + workTime)
  })

  return function (n) {
    return time >= n
  }
}

/**
 * 防抖
 * @param {回调函数} fn
 * @param {延迟时间} delay
 * @returns
 */
export const useDebounce = function (fn, delay = 500) {
  const { current } = useRef({
    fn,
    timer: null
  })

  useEffect(() => {
    current.fn = fn
  }, [fn])

  return useCallback(function (...args) {
    if (current.timer) {
      clearTimeout(current.timer)
    }
    current.timer = setTimeout(() => {
      current.fn.call(this, ...args)
    }, delay)
  })
}

/**
 *
 * @param {回调函数} fn
 * @param {延迟时间} delay
 * @param {立即执行} immediate
 * @returns
 */
export const useThrottle = function (fn, delay = 1000, immediate = false) {
  const { current } = useRef({
    fn,
    timer: null,
    pre: null
  })

  useEffect(() => {
    current.fn = fn
  }, [fn])

  return useCallback(function (...args) {
    //时间戳
    if (immediate) {
      if (!current.pre || Date.now() - current.pre >= delay) {
        current.fn.call(null, ...args)
        current.pre = Date.now()
      }
    } else {
      if (current.timer) {
        return
      }
      current.timer = setTimeout(() => {
        current.fn.call(this, ...args)
        current.timer = null
      }, delay)
    }
  })
}
